import { Meta } from '@storybook/addon-docs';
import { CodeComparison, CodeExample } from './utils.stories';

<Meta title="Concepts/Migration/from v8/Components/Flex/Stack" />

# @fluentui/react - Stack

## Default state

Stack's approach to layout is slightly different from Northstar's Flex, and CSS Flexbox, and a column layout is the default arrangement. For a clean usage scenario of Stack, these are the required CSS properties to achieve the same result:

<CodeComparison>
  <CodeExample title="Render">

    ```jsx
    <div className={styles.root}>{children}</div>
    ```

  </CodeExample>
  <CodeExample title="make-styles">

    ```js
    makeStyles({
      root: {
        display: 'flex',
        flexDirection: 'column',
        flexWrap: 'nowrap',
        width: 'auto',
        height: 'auto',
        boxSizing: 'border-box',
        '> *': {
          textOverflow: 'ellipsis',
        },
        '> :not(:first-child)': {
          marginTop: '0px',
        },
        '> *:not(.ms-StackItem)': {
          flexShrink: 1,
        },
      },
    })
    ```

  </CodeExample>
</CodeComparison>

<CodeComparison>
  <CodeExample>

    ```html
    <div class="flex">
      ...
    </div>
    ```

  </CodeExample>
  <CodeExample>

    ```css
    .flex {
      display: flex;
      flex-direction: column;
      flex-wrap: nowrap;
      width: auto;
      height: auto;
      box-sizing: border-box;
    }
    .flex > * {
      text-overflow: ellipsis;
    }
    .flex > :not(:first-child) {
      margin-top: 0px;
    }
    .flex > *:not(.ms-StackItem) {
      flex-shrink: 1;
    }
    ```

  </CodeExample>
</CodeComparison>

MDN documentation:

- [display](https://developer.mozilla.org/en-US/docs/Web/CSS/display)
- [flex-direction](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction)
- [flex-wrap](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap)
- [width](https://developer.mozilla.org/en-US/docs/Web/CSS/width)
- [height](https://developer.mozilla.org/en-US/docs/Web/CSS/height)
- [box-sizing](https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing)
- [text-overflow](https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflow)
- [margin-top](https://developer.mozilla.org/en-US/docs/Web/CSS/margin-top)
- [flex-shrink](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-shrink)

---

## as

The `as` property strictly replaces which element type will be rendered as the root node. The default value for this is `div`.

---

## disableShrink

<CodeComparison>
  <CodeExample>

    ```js
    makeStyles({
      root: {
        '> *': {
          flexShrink: 0,
        }
      },
    })
    ```

  </CodeExample>
  <CodeExample>

    ```css
    .flex > * {
      flex-shrink: 0;
    }
    ```

  </CodeExample>
</CodeComparison>

MDN documentation:

- [flex-shrink](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-shrink)

---

## gap

_`10px` is used below as an example value_

<CodeComparison>
  <CodeExample>

    ```js
    makeStyles({
      root: {
        '> *': {
          margin: '10px',
        }
      },
    })
    ```

  </CodeExample>
  <CodeExample>

    ```css
    .flex > * {
      margin: 10px;
    }
    ```

  </CodeExample>
</CodeComparison>

If you want to replicate the exact behavior of the prop, you'll have to keep in mind the following:

- For horizontal layouts, you need to apply the margin to either left or right.
- For vertical layouts, you need to apply the margin to either top or bottom.

To keep the margin only between the items, you can prevent it from being applied to the last (or first) element.
Heres an example with an horizontal layout and margin-right:

_`10px` is used below as an example value_

<CodeComparison>
  <CodeExample>

    ```js
    makeStyles({
      root: {
        display: 'flex',
        flexDirection: 'row',
        '> :not(:last-child)': {
          marginRight: '10px',
        }
      },
    })
    ```

  </CodeExample>
  <CodeExample>

    ```css
    .flex {
      display: flex;
      flex-direction: row;
    }
    .flex > :not(:last-child) {
      margin-right: 10px;
    }
    ```

  </CodeExample>
</CodeComparison>

As an alternative to this implementation, you can also use the CSS `gap` property. However, keep in mind that this is not the implementation in Stack, given that CSS `gap` is not supported by Internet Explorer 11, and might produce different results.
If you do not have this limitation, you can use the following CSS:

_`10px` is used below as an example value_

<CodeComparison>
  <CodeExample>

    ```js
    makeStyles({
      root: {
        display: 'flex',
        flexDirection: 'row',
        gap: '10px',
      },
    })
    ```

  </CodeExample>
  <CodeExample>

    ```css
    .flex {
      display: flex;
      flex-direction: row;
      gap: 10px;
    }
    ```

  </CodeExample>
</CodeComparison>

MDN documentation:

- [display](https://developer.mozilla.org/en-US/docs/Web/CSS/display)
- [flex-direction](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction)
- [margin](https://developer.mozilla.org/en-US/docs/Web/CSS/margin)
- [gap](https://developer.mozilla.org/en-US/docs/Web/CSS/gap)

---

## grow

<CodeComparison>
  <CodeExample>

    ```js
    makeStyles({
      root: {
        '> *': {
          flexGrow: 1,
        }
      },
    })
    ```

  </CodeExample>
  <CodeExample>

    ```css
    .flex > * {
      flex-grow: 1;
    }
    ```

  </CodeExample>
</CodeComparison>

MDN documentation:

- [flex-grow](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-grow)

---

## horizontal

<CodeComparison>
  <CodeExample>

    ```js
    makeStyles({
      root: {
        flexDirection: 'row',
      },
    })
    ```

  </CodeExample>
  <CodeExample>

    ```css
    .flex {
      flex-direction: row;
    }
    ```

  </CodeExample>
</CodeComparison>

MDN documentation:

- [flex-direction](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction)

---

## horizontalAlign / verticalAlign

horizontalAlign/verticalAlign change which props they affect depending on your `flex-direction`.

Here is a table you can follow for which prop to use for alignment:

| Direction  | `flex-direction` | Horizontal alignment | Vertical alignment |
| ---------- | ---------------- | -------------------- | ------------------ |
| default    | column           | align-items          | justify-content    |
| horizontal | row              | justify-content      | align-items        |

You can also refer to [this MDN page](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Aligning_Items_in_a_Flex_Container) for a great in depth explanation about how alignment works in flex container.

MDN documentation:

- [flex-direction](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction)
- [justify-content](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content)
- [align-items](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items)

---

## maxHeight

_`10px` is used below as an example value_

<CodeComparison>
  <CodeExample>

    ```js
    makeStyles({
      root: {
        '> *': {
          maxHeight: '10px',
        }
      },
    })
    ```

  </CodeExample>
  <CodeExample>

    ```css
    .flex > * {
      max-height: 10px;
    }
    ```

  </CodeExample>
</CodeComparison>

MDN documentation:

- [max-height](https://developer.mozilla.org/en-US/docs/Web/CSS/max-height)

---

## maxWidth

_`10px` is used below as an example value_

<CodeComparison>
  <CodeExample>

    ```js
    makeStyles({
      root: {
        '> *': {
          maxWidth: '10px',
        }
      },
    })
    ```

  </CodeExample>
  <CodeExample>

    ```css
    .flex > * {
      max-width: 10px;
    }
    ```

  </CodeExample>
</CodeComparison>

MDN documentation:

- [max-width](https://developer.mozilla.org/en-US/docs/Web/CSS/max-width)

---

## padding

_`10px` is used below as an example value_

<CodeComparison>
  <CodeExample>

    ```js
    makeStyles({
      root: {
        padding: '10px',
      },
    })
    ```

  </CodeExample>
  <CodeExample>

    ```css
    .flex {
      padding: 10px;
    }
    ```

  </CodeExample>
</CodeComparison>

MDN documentation:

- [padding](https://developer.mozilla.org/en-US/docs/Web/CSS/padding)

---

## reversed

`reversed` will append "reverse" to your `flex-direction` CSS prop. Below is a table to reflect what you should use:

| Alignment  | CSS    | With `reversed` prop |
| ---------- | ------ | -------------------- |
| default    | column | column-reverse       |
| horizontal | row    | row-reverse          |

Example usage for an horizontal layout:

<CodeComparison>
  <CodeExample>

    ```js
    makeStyles({
      root: {
        flexDirection: 'row-reverse',
      },
    })
    ```

  </CodeExample>
  <CodeExample>

    ```css
    .flex {
      flex-direction: row-reverse;
    }
    ```

  </CodeExample>
</CodeComparison>

MDN documentation:

- [flex-direction](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction)

---

## verticalFill

<CodeComparison>
  <CodeExample>

    ```js
    makeStyles({
      root: {
        height: '100%',
      },
    })
    ```

  </CodeExample>
  <CodeExample>

    ```css
    .flex {
      height: 100%;
    }
    ```

  </CodeExample>
</CodeComparison>

MDN documentation:

- [height](https://developer.mozilla.org/en-US/docs/Web/CSS/height)

---

## wrap

The `wrap` prop will also change the rendering. As such find below the styles and rendering being applied:

<CodeComparison>
  <CodeExample title="Render">

    ```jsx
    <div className={styles.root}>
      <div className={styles.inner}>
        {children}
      </div>
    </div>
    ```

  </CodeExample>
  <CodeExample title="make-styles">

    ```js
    makeStyles({
      root: {
        flexWrap: 'wrap',
        overflow: 'visible',
        height: '100%',
      },
      inner: {
        display: 'flex',
        flexWrap: 'wrap',
        overflow: 'visible',
        boxSizing: 'border-box',
        width: '100%',
        maxWidth: '100vw',
      }
    })
    ```

  </CodeExample>
</CodeComparison>
<CodeComparison>
  <CodeExample>

    ```html
    <div class="flex">
      <div class="inner">
        ...
      </div>
    </div>
    ```

  </CodeExample>
  <CodeExample>

    ```css
    .flex {
      flex-wrap: wrap;
      overflow: visible;
      height: 100%;
    }
    .inner {
      display: flex;
      flex-wrap: wrap;
      overflow: visible;
      box-sizing: border-box;
      width: 100%;
      max-width: 100vw;
    }
    ```

  </CodeExample>
</CodeComparison>

MDN documentation:

- [flex-wrap](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap)
- [overflow](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow)
- [display](https://developer.mozilla.org/en-US/docs/Web/CSS/display)
- [box-sizing](https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing)
- [height](https://developer.mozilla.org/en-US/docs/Web/CSS/height)
- [width](https://developer.mozilla.org/en-US/docs/Web/CSS/width)
- [max-width](https://developer.mozilla.org/en-US/docs/Web/CSS/max-width)
